[Design Pattern] 퍼사드(Facade) 패턴
업데이트:
✅ 퍼사드 패턴이란?
퍼사드(Facade) 패턴은 복잡한 시스템이나 서브시스템을 간략한 인터페이스를 통해 제공하여 시스템의 복잡성을 감소시키고 사용하기 편리하게 만들어주는 패턴이다. 복잡한 시스템을 감싸고 있는 외부 인터페이스를 제공하여 시스템 간의 의존성을 낮추고, 클라이언트가 시스템의 내부 구조에 대해 알 필요 없이 사용할 수 있게 해준다.
퍼사드 패턴의 핵심 요소는 “퍼사드” 클래스이다. 퍼사드 클래스를 통해 시스템의 복잡한 부분을 캡슐화하고, 간단한 인터페이스를 제공한다. 클라이언트는 이 퍼사드 클래스를 사용하여 서브시스템과 상호작용 한다.
✅ 퍼사드 패턴의 구성 요소
-
Facade
클라이언트와 내부 시스템 간의 중간 계층으로 작용하는 인터페이스를 제공한다. 복잡한 서브 시스템에 대한 단순한 메소드들로 구성된다.
-
Subsystem Classes
퍼사드 클래스에 의해 감싸지는 복잡한 서브시스템의 클래스들을 의미한다. 이 클래스들이 시스템의 핵심 로직을 구현한다.
-
Client
Facade를 사용하여 복잡한 시스템을 간편하게 사용하는 클라이언트이다.
✅ 퍼사드 패턴의 구조
- 퍼사드 패턴을 사용하면 하위 시스템 기능들의 특정 부분에 편리하게 접근할 수 있다.
- 추가적인 퍼사드 클래스는 관련없는 기능들이 포함되어 복잡한 구조로 퍼사드 클래스가 변질되는 것을 방지할 수 있다.
- 복잡한 하위 시스템은 수십 개의 다양한 객체들로 구성된다. 모든 객체가 의미있는 작업을 수행하도록 하려면, 하위 시스템의 세부적인 구현 정보를 깊이 있게 알아야 한다. 이때 하위 시스템 클래스들은 퍼사드 클래스의 존재를 인식하지 못한다.
- 클라이언트는 하위 시스템 객체를 직접 호출하는 것 대신 퍼사드 클래스를 통해 하위 시스템 객체를 사용한다.
📌 퍼사드 패턴 의사코드
// 복잡한 비디오 변환 프레임워크 클래스의 일부이다.
// 해당 프레임워크 코드는 우리가 제어할 수 없기 때문에 단순화할 수 없다.
class VideoFile
// …
class OggCompressionCodec
// …
class MPEG4CompressionCodec
// …
class CodecFactory
// …
class BitrateReader
// …
class AudioMixer
// …
// 퍼사드 클래스를 만들어 프레임워크의 복잡성을 간단한 인터페이스 뒤에 숨길 수
// 있다. 기능성과 단순함을 상호보완한다.
class VideoConverter is
method convert(filename, format):File is
file = new VideoFile(filename)
sourceCodec = (new CodecFactory).extract(file)
if (format == "mp4")
destinationCodec = new MPEG4CompressionCodec()
else
destinationCodec = new OggCompressionCodec()
buffer = BitrateReader.read(filename, sourceCodec)
result = BitrateReader.convert(buffer, destinationCodec)
result = (new AudioMixer()).fix(result)
return new File(result)
// 애플리케이션 클래스들은 복잡한 프레임워크에서 제공하는 수많은 클래스에 의존하지
// 않는다. 또한 프레임워크의 전환을 결정한 경우에는 퍼사드 클래스만 다시 작성하면 된다.
class Application is
method main() is
convertor = new VideoConverter()
mp4 = convertor.convert("funny-cats-video.ogg", "mp4")
mp4.save()
✅ 퍼사드 패턴을 사용하는 이유
-
단순한 인터페이스 제공
복잡한 시스템에 대해 단순한 인터페이스를 제공하여 클라이언트가 시스템의 내부 동작을 이해할 필요 없이 사용할 수 있다.
-
시스템 간의 의존성 낮춤
Facade 패턴은 시스템의 내부 구조를 숨기기 때문에, 시스템 간의 의존성을 줄여서 시스템을 변경하거나 유지보수 하기 쉽게 만든다.
-
구조적 복잡성 감소
복잡한 시스템을 여러 개의 간단한 서브시스템으로 분할하고, 이를 Facade를 통해 조합함으로써 구조적 복잡성을 줄일 수 있다.
✅ 퍼사드 패턴 적용 상황
-
라이브러리의 사용
자주 사용하는 기능을 라이브러리로 제공할 때, 라이브러리 내부의 복잡한 기능을 Facade를 통해 단순화하여 사용자가 쉽게 사용할 수 있게 한다.
// 서브시스템 1: 가계부 데이터 관리
class AccountBook {
public void addExpense(String category, double amount) {
// 가계부에 지출 내역 추가
System.out.println("Added expense of $" + amount + " to category: " + category);
}
public void addIncome(String source, double amount) {
// 가계부에 수입 내역 추가
System.out.println("Added income of $" + amount + " from source: " + source);
}
}
// 서브시스템 2: 가계부 보고서 생성
class ReportGenerator {
public void generateMonthlyReport() {
// 월간 보고서 생성
System.out.println("Generated monthly report");
}
public void generateYearlyReport() {
// 연간 보고서 생성
System.out.println("Generated yearly report");
}
}
// 퍼사드 클래스: 클라이언트에게 단순한 인터페이스를 제공
class AccountFacade {
private AccountBook accountBook;
private ReportGenerator reportGenerator;
public AccountFacade() {
this.accountBook = new AccountBook();
this.reportGenerator = new ReportGenerator();
}
// 가계부에 지출 추가 메서드
public void addExpense(String category, double amount) {
accountBook.addExpense(category, amount);
}
// 가계부에 수입 추가 메서드
public void addIncome(String source, double amount) {
accountBook.addIncome(source, amount);
}
// 월간 보고서 생성 메서드
public void generateMonthlyReport() {
reportGenerator.generateMonthlyReport();
}
// 연간 보고서 생성 메서드
public void generateYearlyReport() {
reportGenerator.generateYearlyReport();
}
}
// 클라이언트
public class Client {
public static void main(String[] args) {
// 퍼사드를 통해 간단한 인터페이스로 서브시스템을 사용
AccountFacade accountFacade = new AccountFacade();
// 가계부 작업
accountFacade.addExpense("Groceries", 50.00);
accountFacade.addIncome("Salary", 2000.00);
// 보고서 생성
accountFacade.generateMonthlyReport();
accountFacade.generateYearlyReport();
}
}
댓글남기기